package com.qihetimes.earthangel.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qihetimes.earthangel.common.ConfigType;
import com.qihetimes.earthangel.common.IntegralChangeType;
import com.qihetimes.earthangel.common.MessageType;
import com.qihetimes.earthangel.mapper.IntegralRecordMapper;
import com.qihetimes.earthangel.model.Goods;
import com.qihetimes.earthangel.model.IntegralRecord;
import com.qihetimes.earthangel.model.User;
import com.qihetimes.earthangel.service.IConfigService;
import com.qihetimes.earthangel.service.IConversationService;
import com.qihetimes.earthangel.service.IIntegralRecordService;
import com.qihetimes.earthangel.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 积分记录表 服务实现类
 * </p>
 *
 * @author f4cklangzi@gmail.com
 * @since 2022-01-12
 */
@Service
public class IntegralRecordServiceImpl extends ServiceImpl<IntegralRecordMapper, IntegralRecord> implements IIntegralRecordService {
    
    @Resource
    private IUserService userService;
    
    @Resource
    private IConfigService configService;
    
    @Resource
    private IConversationService conversationService;
    
    /**
     * 由于物品导致的积分变动(同一个物品同一个类型只会变动一次)
     *
     * @param type  变动类型
     * @param goods 物品
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeIntegralByGoods(IntegralChangeType type, Goods goods) {
        String userId = goods.getUserId();
        if (IntegralChangeType.GET_GOODS.equals(type)) {
            userId = goods.getToUserId();
        }
        User user = userService.getById(userId);
        Integer count = lambdaQuery()
            .eq(IntegralRecord::getUserId, user.getId())
            .eq(IntegralRecord::getChangeType, type)
            .eq(IntegralRecord::getGoodsId, goods.getId())
            .count();
        if (count > 0) {
            return;
        }
        IntegralRecord record = new IntegralRecord();
        record.setId(IdUtil.objectId());
        record.setUserId(user.getId());
        record.setGoodsId(goods.getId());
        record.setChangeType(type.name());
        ConfigType.IntegralConfig config = configService.getIntegralConfig();
        Integer changeCount = 0;
        switch (type) {
            case UPLOAD_GOODS:
                changeCount += config.getUploadGoods();
                break;
            case SEND_GOODS:
                changeCount += config.getSendGoods();
                if (goods.getOriginalPrice() == null) {
                    break;
                }
                changeCount += goods.getOriginalPrice().multiply(new BigDecimal(String.valueOf(config.getSendGoodsOriginalPriceRatio()))).intValue();
                break;
            case GET_GOODS:
                changeCount += config.getGetGoods();
                break;
            case SHARE_GOODS:
                changeCount += config.getShareGoods();
                break;
            default:
        }
        record.setChangeCount(changeCount);
        record.setRemark(type.getMark() + "-" + goods.getName());
        record.setCreatedAt(LocalDateTime.now());
        save(record);
        Integer oldIntegral = user.getIntegral();
        int newIntegral = oldIntegral + changeCount;
        int oldLevel = user.getLevel();
        int newLevel = oldLevel;
        List<Integer> leveIntegralList = config.getLeveIntegralList();
        for (int i = leveIntegralList.size() - 1; i >= 0; i--) {
            if (newIntegral >= leveIntegralList.get(i)) {
                newLevel = i;
                break;
            }
        }
        userService.lambdaUpdate().eq(User::getId, user.getId())
            .set(User::getIntegral, newIntegral)
            .set(User::getLevel, newLevel)
            .update();
        JSONObject json = new JSONObject();
        json.set("oldIntegral", oldIntegral);
        json.set("newIntegral", newIntegral);
        json.set("oldLevel", oldLevel);
        json.set("newLevel", newLevel);
        json.set("changeType", type);
        String content = JSONUtil.toJsonStr(json);
        conversationService.sendSystemMessage(MessageType.INTEGRAL_CHANGE, user, content, true);
    }
}
